package cn.wlinker.video.monitor.brand.hikversion.create.net.aop;

import cn.wlinker.video.monitor.brand.hikversion.create.net.HCNetTools;
import cn.wlinker.video.monitor.brand.hikversion.create.net.config.NetConfig;
import cn.wlinker.video.monitor.brand.hikversion.create.net.utils.HikCameraUtils;
import cn.wlinker.video.monitor.brand.hikversion.utils.NetDeviceCacheUtils;
import cn.wlinker.video.monitor.domain.dto.MonitorDeviceDTO;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.lang.reflect.Method;

/**
 * 海康设备登陆AOP切面
 */
@Aspect
@Component
public class HikCameraAspect {

    private final Logger logger = LoggerFactory.getLogger(HikCameraAspect.class);

    @Around(value = "execution(* cn.wlinker.video.monitor.brand.hikversion.create.NetStreamServiceImpl.*(..))")
    public synchronized Object aroundCamera(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        String deviceCode = null;
        try {
            // 获取方法签名和Method对象
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            // 1. 获取参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            // 2. 获取参数名称
            ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
            Object[] args = joinPoint.getArgs();
            // 将参数名称与类型、值关联（可选）
            if(parameterNames != null){
                for (int i = 0; i < parameterNames.length; i++) {
                    if("deviceCode".equals(parameterNames[i])){
                        deviceCode = (String) args[i];
                        break;
                    }
                    if("MonitorDeviceDTO".equals(parameterTypes[i].getSimpleName())){
                        MonitorDeviceDTO monitorDeviceDTO = (MonitorDeviceDTO) args[i];
                        deviceCode = monitorDeviceDTO.getDeviceCode();
                        break;
                    }
                }
            }
            Assert.notNull(deviceCode, "id和deviceCode不能为同时为空");
            //设备登录
            logout(deviceCode);
            int code = login(deviceCode);
            switch (code) {
                case 0:
                    //成功登录
                    result = joinPoint.proceed(args);
                    break;
                case 4:
                    //获取通道失败
                    throw new RuntimeException("获取通道失败");
                default:
                    throw new RuntimeException(HikCameraUtils.resultNames[code]);
            }
            return result;
        } catch (Throwable e) {
            logger.error("目标方法执行异常,目标类:{}方法：{}", joinPoint.getTarget(), joinPoint.getSignature().getName(), e);
            throw e;
        } finally {
            if(deviceCode != null){
                logout(deviceCode);
            }
        }
    }

    public synchronized int login(String deviceCode) {
        int code = 0;
        HCNetTools hcTool = NetDeviceCacheUtils.getHcNetTools(deviceCode);
//        if (hcTool.initDevices() == 1) {
//            code = 1;//初始化失败
//            return code;
//        }
        NetConfig netConfig = NetDeviceCacheUtils.getNetConfig(deviceCode);
        int regSuc = hcTool.deviceLogin(netConfig.getUsername(), netConfig.getPassword(), netConfig.getHost(), netConfig.getPort());
        if (regSuc != 0) {
            //注册失败
            code = regSuc;
            return code;
        }
//        List<String> channelList;
//        channelList = hcTool.getChannelNumber();
//        StaticLog.info("{}", channelList);
//        if (channelList.size() == 0) code = 4;

        return code;
    }

    public synchronized void logout(String deviceCode) {
        HCNetTools hcTool = NetDeviceCacheUtils.getHcNetTools(deviceCode);
        hcTool.deviceLogout();
    }

}
